#include "chatserver.hpp"
#include "json.hpp"
#include "chatservice.hpp"

#include <functional>
#include <string>
using namespace std;
using namespace placeholders;
using json = nlohmann::json;

// 初始化聊天服务器对象
ChatServer::ChatServer(EventLoop *loop,               // 事件循环
           const InetAddress &listenAddr, // IpPort
           const string &nameArg)
           :_server(loop, listenAddr, nameArg)
           ,_loop(loop)
{
    // 注册连接回调
    _server.setConnectionCallback(std::bind(&ChatServer::onConnection, this, _1));
    
    // 注册消息回调
    _server.setMessageCallback(std::bind(&ChatServer::onMessage, this, _1, _2, _3));

    // 设置线程数量
    _server.setThreadNum(4);
}

void ChatServer::start()
{
    _server.start();
}

// 上报连接相关信息的回调函数，连接建立、断开回调
void ChatServer::onConnection(const TcpConnectionPtr &conn)
{
    // 客户端断开连接
    if(!conn->connected())
    {
        ChatService::getInstance()->clientCloseException(conn);
        conn->shutdown();  // 释放socket资源
    }
}

// 上报读写信息相关回调
void ChatServer::onMessage(const TcpConnectionPtr &conn, Buffer *buffer, Timestamp time)
{
    string buf = buffer->retrieveAllAsString();  // 获取冲区里的数据以string形式
    json js = json::parse(buf);  // 数据反序列化成json
    
    // 如果这里根据消息类型调用相应方法，就得写if else... 直接调用服务层方法 → 耦合
    // 目的：解耦合，完全解耦网络模块和业务模块的代码  面向接口的编程 or 回调函数
    // 通过js["msgid"]获取 → 业务处理器handler → conn js time 
    // 获取对应的消息处理器
    auto msgHandler = ChatService::getInstance()->getHander(js["msgid"].get<int>());
    // 回调消息绑定好的事件处理器，来执行相应的业务处理
    msgHandler(conn, js, time);
}